#ifndef YHAIDA_ATOMIC_H
#define YHAIDA_ATOMIC_H
#include <stdint.h>
#include <atomic>
#include "../base/Utils.h"

namespace yhaida
{
    template <typename T>
    class AtomicInt : Utils::nocapyable
    {
    public:
        AtomicInt() : _value(0){};
        ~AtomicInt() = default;
        //“无锁”代码
        T get()
        {
            //__sync_val_compare_and_swap(当前值,old,new)指令
            //在写入新值之前， 读出旧值， 当且仅当旧值与存储中的当前值一致时，才把新值写入存储；
            return __sync_val_compare_and_swap(&_value, 0, 0);
        }

        T getAndAdd(T x)
        {
            return __sync_fetch_and_add(&_value, x);
        }

        T addAndGet(T x)
        {
            return __sync_add_and_fetch(&_value, x);
        }

        T incrementAndGet()
        {
            return addAndGet(1);
        }

        T decrementAndGet()
        {
            return addAndGet(-1);
        }

        void increment()
        {
            incrementAndGet();
        }

        void decrement()
        {
            decrementAndGet();
        }

        T getAndSet(T newValue)
        {
            // in gcc >= 4.7: __atomic_exchange_n(&value_, newValue, __ATOMIC_SEQ_CST)
            return __sync_lock_test_and_set(&_value, newValue);
        }

    private:
        //使用volatile防止编译器优化
        volatile T _value;
    };
    //使用确切的int位数的类型
    typedef yhaida::AtomicInt<int32_t> AtomicInt32;
    typedef yhaida::AtomicInt<int64_t> AtomicInt64;
}

#endif